/******************************************************************************
*File   : HashCode.h
*Author : Lan Hu
*Email	: Hi_Blue@126.com
*Notes	:
*Licence: 
*Created: 2009-09-23
*******************************************************************************/

#ifndef _MYLIB_HASHCODE_H__INCLUDE_20090923_
#define _MYLIB_HASHCODE_H__INCLUDE_20090923_

#include "public.h"
#include "Thread.h"


M_BEGIN_NAMESPACE(mylib)

class HashCode
{
public:
	typedef uint64 T_KEY;

	enum HASH_TYPE
	{
		E_HASH_OFFSET	= 0, 
		E_HASH_A		= 1, 
		E_HASH_B		= 2
	};

private:

	bool m_bInitialized;
	static T_KEY cryptTable[0x500];
	static ThreadMutex m_Mutex;

public:
	HashCode()
	{
		prepareCryptTable();
	}

	~HashCode()	{ }

	T_KEY getHashCode( char *szKey, T_KEY iHashType = E_HASH_OFFSET )
	{
		assert(m_bInitialized);
		byte *iKey = (byte*)szKey;
		T_KEY seed1 = 0x7FED7FED;
		T_KEY seed2 = 0xEEEEEEEE;
		int ch;

		while( *iKey != 0 )
		{
			ch = *iKey++;
			//ch = toupper(*iKey++);
			seed1 = cryptTable[(iHashType << 8) + ch] ^ (seed1 + seed2);
			seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
		}
		return seed1;
	}

	T_KEY operator()( char *szKey, T_KEY iHashType = E_HASH_OFFSET )
	{
		assert(m_bInitialized);
		byte *iKey = (byte*)szKey;
		T_KEY seed1 = 0x7FED7FED;
		T_KEY seed2 = 0xEEEEEEEE;
		int ch;

		while( *iKey != 0 )
		{
			ch = *iKey++;
			//ch = toupper(*iKey++);
			seed1 = cryptTable[(iHashType << 8) + ch] ^ (seed1 + seed2);
			seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
		}
		return seed1;
	}

private:
	void prepareCryptTable()
	{
		m_Mutex.lock();
		if(m_bInitialized) return ;
		T_KEY seed = 0x00100001, index1 = 0, index2 = 0, i;
		for( index1 = 0; index1 < 0x100; index1++ )
		{
			for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 )
			{
				uint32 temp1, temp2;

				seed = (seed * 125 + 3) % 0x2AAAAB;
				temp1 = (seed & 0xFFFF) << 0x10;

				seed = (seed * 125 + 3) % 0x2AAAAB;
				temp2 = (seed & 0xFFFF);

				cryptTable[index2] = ( temp1 | temp2 );
			}
		}
		m_bInitialized = true;
		m_Mutex.unlock();
	}
};

HashCode::T_KEY HashCode::cryptTable[0x500] = {0};

ThreadMutex HashCode::m_Mutex;

M_END_NAMESPACE(mylib)

#endif	//_MYLIB_HASHCODE_H__INCLUDE_20090923_

